﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace 凌依.工具库.U3D空间计算
{
    /// <summary>
    /// 对坐标,空间相关处理的函数
    /// </summary>
    public class 空间计算
    {
        /// <summary>
        /// 获取画布下鼠标坐标
        /// </summary>
        /// <param name="画布"></param>
        /// <returns></returns>
        public static Vector2 获取局部鼠标坐标(Canvas 画布)
        {
            Vector2 坐标;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(画布.transform as RectTransform, Input.mousePosition, null, out 坐标);
            return 坐标;
        }
        public static Vector2 获取局部鼠标坐标(Transform 画布)
        {
            Vector2 坐标;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(画布 as RectTransform, Input.mousePosition, null, out 坐标);
            return 坐标;
        }
        public static Vector2 获取局部鼠标坐标(RectTransform 画布)
        {
            Vector2 坐标;
            RectTransformUtility.ScreenPointToLocalPointInRectangle(画布, Input.mousePosition, null, out 坐标);
            return 坐标;
        }
        /// <summary>
        /// 返回0-2的浮点数
        /// </summary>
        /// <param name="目标"></param>
        /// <param name="自身"></param>
        /// <returns></returns>
        public static float 获得方向(Transform 目标, Transform 自身)
        {
            Vector3 dir = 目标.position - 自身.position;
            float 方向 = Vector3.Dot(自身.up, 目标.position - 自身.position);
            Vector3 cross = Vector3.Cross(自身.up, dir.normalized);
            float 结果 = cross.z;
            if (方向 <= 0)
            {
                if (结果 < 0)
                    结果 = (1 + 结果) - (1 + 结果) * 2 - 1;
                else
                    结果 = (1 - 结果) + 1;
            }
            return 结果;

        }
        /// <summary>
        /// 返回两物体之间直线距离
        /// </summary>
        /// <param name="目标">顺序无所谓</param>
        /// <param name="自身">顺序无所谓</param>
        /// <returns></returns>
        public static float 相距(Transform 目标, Transform 自身)
        {
            return (目标.position - 自身.position).magnitude;
        }
        /// <summary>
        /// 计算两坐标之间直线距离
        /// </summary>
        /// <param name="目标">顺序无所谓</param>
        /// <param name="自身">顺序无所谓</param>
        /// <returns></returns>
        public static float 相距(Vector3 目标, Vector3 自身)
        {
            return (目标 - 自身).magnitude;
        }
        #region 瞄准_角度相关代码
        /// <summary>
        /// 自动瞄准目标
        /// </summary>
        /// <param name="目标"></param>
        /// <param name="自身"></param>
        /// <param name="轴向">哪一个轴朝向目标    类库.枚举.方向.x</param>
        public static void 角度计算(Transform 目标, Transform 自身, Vector3 轴向)
        {
            Vector3 v = 目标.position - 自身.position;
            自身.rotation = Quaternion.FromToRotation(轴向, v);
        }
        public static void 角度计算(Transform 自身, Vector3 目标, Vector3 轴向)
        {
            Vector3 v = 目标 - 自身.position;
            自身.rotation = Quaternion.FromToRotation(轴向, v); 
        }
        public static Quaternion 角度计算(Vector3 自身, Vector3 目标, Vector3 轴向)
        {
            Vector3 v = 目标 - 自身;
            return Quaternion.FromToRotation(轴向, v);
        }
        /// <summary>
        /// 返回eulerAngles
        /// </summary>
        /// <param name="自身"></param>
        /// <param name="目标"></param>
        /// <returns></returns>
        public static Vector3 角度计算_2d(Vector3 自身,Vector3 目标)
        {
            Vector3 方向 = (目标 - 自身).normalized;
            return new Vector3(0, 0, Mathf.Atan2(方向.y, 方向.x) * Mathf.Rad2Deg);
        }

        public static void 角度计算_2d(Transform 自身, Vector3 目标)
        {
            Vector3 方向 = (目标 - 自身.position).normalized;
             自身.eulerAngles = new Vector3(0, 0, Mathf.Atan2(方向.y, 方向.x) * Mathf.Rad2Deg);
        }



        public static void 瞄准_三维前进(Transform 自身, Vector3 目标坐标, Vector3 轴向, float 速度)
        {
            //瞄准
            角度计算(自身, 目标坐标, 轴向);
            自身.Translate(轴向 * Time.deltaTime * 速度, Space.Self);
        }
        public static void 瞄准_二维前进(Transform 自身, Vector3 目标坐标, float 速度)
        {
            //瞄准
            自身.eulerAngles =  角度计算_2d(自身.position, 目标坐标);
            自身.Translate(Vector3.forward * Time.deltaTime * 速度, Space.Self);
        }

        /// <summary>
        /// 缓慢朝向对方需要帧更新
        /// </summary>
        /// <param name="自身"></param>
        /// <param name="目标"></param>
        /// <param name="角速度"></param>
        /// <param name="距离"></param>
        public static void 插值转向(Transform 自身, Transform 目标, float 角速度, out float 距离)
        {
            //显示自身与目标距离(橙色)可删除
            Debug.DrawLine(目标.position, 自身.position, Color.yellow);

            //核心在代码网上找的我不懂原理
            自身.rotation = Quaternion.Slerp(自身.rotation, Quaternion.LookRotation(目标.position - 自身.position), 角速度 * Time.deltaTime);
            //显示当前转向角度(红色)可删除
            距离 = (目标.position - 自身.position).magnitude;
            Debug.DrawLine(自身.position, 自身.position + 自身.forward * 距离, Color.red);
        }

        public static void 插值转向(Transform 自身, Transform 目标, float 角速度)
        {
            Debug.DrawLine(目标.position, 自身.position, Color.yellow);

            自身.rotation = Quaternion.Slerp(自身.rotation, Quaternion.LookRotation(目标.position - 自身.position), 角速度 * Time.deltaTime);

            Debug.DrawLine(自身.position, 自身.position + 自身.forward * (目标.position - 自身.position).magnitude, Color.red);
        }

        public static void 插值转向(Transform 自身, Vector3 目标, float 角速度)
        {
            Debug.DrawLine(目标, 自身.position, Color.yellow);

            自身.rotation = Quaternion.Slerp(自身.rotation, Quaternion.LookRotation(目标 - 自身.position), 角速度 * Time.deltaTime);

            Debug.DrawLine(自身.position, 自身.position + 自身.forward * (目标 - 自身.position).magnitude, Color.red);
        }

        public static void 插值转向_2d(Transform 自身, Vector3 目标, float 角速度)
        {
            float angle = Vector3.SignedAngle(自身.right, 目标 - 自身.position, Vector3.forward);
            自身.Rotate(new Vector3(0, 0, Mathf.Sign(angle) * 角速度 * Time.deltaTime));

        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="自身角度"></param>
        /// <param name="方向"></param>
        /// <param name="进度">0-1百分比</param>
        /// <returns></returns>
        public static Quaternion 插值转向(Quaternion 自身角度,Vector3 方向,float 进度)
        {
            return Quaternion.Slerp(自身角度, Quaternion.LookRotation(方向), 进度);
        }
        /// <summary>
        /// 获得角度偏差
        /// </summary>
        /// <param name="自身"></param>
        /// <param name="目标"></param>
        /// <returns></returns>
        public static Vector3 获得方向(Vector3 自身,Vector3 目标)
        {
            return 目标 - 自身;
        }

        #endregion

        #region 坐标转换
        public static Vector3Int 坐标转换(Vector2Int 值)
        {
            return new Vector3Int(值.x, 值.y, 0);
        }
        public static Vector3 坐标转换(Vector2 值)
        {
            return new Vector3(值.x, 值.y, 0);
        }

        public static Vector2 坐标转换(Vector3 值)
        {
            return new Vector2(值.x, 值.y);
        }

        public static Vector2Int 坐标转换(Vector3Int 值)
        {
            return new Vector2Int(值.x, 值.y);
        }


        public static Vector2Int 坐标偏移(Vector2Int 坐标, int x, int y)
        {
            return new Vector2Int(坐标.x + x, 坐标.y + y);
        }

        public static Vector2 坐标偏移(Vector2 坐标, float x, float y)
        {
            return new Vector2(坐标.x + x, 坐标.y + y);
        }
        public static Vector2 坐标偏移(Vector2Int 坐标, float x, float y)
        {
            return new Vector2(坐标.x + x, 坐标.y + y);
        }
        #endregion

        public static Vector2Int[] 获取_周围2维坐标(Vector2Int 坐标)
        {

            Vector2Int[] jg = new Vector2Int[8];
            jg[0] = 坐标 + new Vector2Int(0, 1);
            jg[1] = 坐标 + new Vector2Int(0, -1);
            jg[2] = 坐标 + new Vector2Int(1, 0);
            jg[3] = 坐标 + new Vector2Int(-1, 0);
            jg[4] = 坐标 + new Vector2Int(1, 1);
            jg[5] = 坐标 + new Vector2Int(-1, -1);
            jg[6] = 坐标 + new Vector2Int(-1, 1);
            jg[7] = 坐标 + new Vector2Int(1, -1);
            return jg;
        }


        public static Vector2 二维移动(Vector2 当前,Vector2 目标,float 进度)
        {
            return Vector2.MoveTowards(当前, 目标, 进度);
        }

    }
}

